import com.google.common.collect.Maps;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author faraday
 * @create 2020-08-26 16:30
 */
public class HashMapPlus {

    @Test
    public void getCapacity() throws Exception {

        Map<String, String> map = new HashMap<>();
        map.put("hollis1", "hollischuang");
        map.put("hollis2", "hollischuang");
        map.put("hollis3", "hollischuang");
        map.put("hollis4", "hollischuang");
        map.put("hollis5", "hollischuang");
        map.put("hollis6", "hollischuang");
        map.put("hollis7", "hollischuang");
        map.put("hollis8", "hollischuang");
        map.put("hollis9", "hollischuang");
        map.put("hollis10", "hollischuang");
        map.put("hollis11", "hollischuang");
        map.put("hollis12", "hollischuang");
        Class<?> mapType = map.getClass();
        Method capacity = mapType.getDeclaredMethod("capacity");
        capacity.setAccessible(true);
        System.out.println("capacity : " + capacity.invoke(map));
        Field size = mapType.getDeclaredField("size");
        size.setAccessible(true);
        System.out.println("size : " + size.get(map));
        Field threshold = mapType.getDeclaredField("threshold");
        threshold.setAccessible(true);
        System.out.println("threshold : " + threshold.get(map));
        Field loadFactor = mapType.getDeclaredField("loadFactor");
        loadFactor.setAccessible(true);
        System.out.println("loadFactor : " + loadFactor.get(map));
        map.put("hollis13", "hollischuang");
        Method capacity2 = mapType.getDeclaredMethod("capacity");
        capacity2.setAccessible(true);
        System.out.println("capacity2 : " + capacity2.invoke(map));
        Field size2 = mapType.getDeclaredField("size");
        size2.setAccessible(true);
        System.out.println("size : " + size2.get(map));
        Field threshold2 = mapType.getDeclaredField("threshold");
        threshold2.setAccessible(true);
        System.out.println("threshold : " + threshold2.get(map));
        Field loadFactor2 = mapType.getDeclaredField("loadFactor");
        loadFactor2.setAccessible(true);
        System.out.println("loadFactor : " + loadFactor2.get(map));
    }

    @Test
    public void aHundredMillion() {
        int aHundredMillion = 10000000;
        Map<Integer, Integer> map = new HashMap<>();
        long s1 = System.currentTimeMillis();
        for (int i = 0; i < aHundredMillion; i++) {
            map.put(i, i);
        }
        long s2 = System.currentTimeMillis();
        System.out.println(" 未初始化容量，耗时 ： " + (s2 - s1));
        Map<Integer, Integer> map1 = new HashMap<>(aHundredMillion / 2);
        long s5 = System.currentTimeMillis();
        for (int i = 0; i < aHundredMillion; i++) {
            map1.put(i, i);
        }
        long s6 = System.currentTimeMillis();
        System.out.println(" 初始化容量 5000000，耗时 ： " + (s6 - s5));
        Map<Integer, Integer> map2 = new HashMap<>(aHundredMillion);
        long s3 = System.currentTimeMillis();
        for (int i = 0; i < aHundredMillion; i++) {
            map2.put(i, i);
        }
        long s4 = System.currentTimeMillis();
        System.out.println(" 初始化容量为 10000000，耗时 ： " + (s4 - s3));
    }

    @Test
    public void kuorong() throws Exception {
        Map<String, String> map = new HashMap<String, String>(1);
        map.put("hahaha", "hollischuang");
        Class<?> mapType = map.getClass();
        Method capacity = mapType.getDeclaredMethod("capacity");
        capacity.setAccessible(true);
        System.out.println("capacity : " + capacity.invoke(map));
        System.out.println(map.get("hahaha"));
    }

//    public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
//        return new HashMap(capacity(expectedSize));
//    }
//
//    static int capacity(int expectedSize) {
//        if (expectedSize < 3) {
//            CollectPreconditions.checkNonnegative(expectedSize, "expectedSize");
//            return expectedSize + 1;
//        } else {
//            return expectedSize < 1073741824 ? (int) ((float) expectedSize / 0.75F + 1.0F) : 2147483647;
//        }
//    }
//
//    public static void main(String[] args) throws Exception {
//        Map<String, String> map = Maps.newHashMapWithExpectedSize(7);
//        Class<?> mapType = map.getClass();
//        Method capacity = mapType.getDeclaredMethod("capacity");
//        capacity.setAccessible(true);
//        System.out.println("capacity : " + capacity.invoke(map));
//    }
}
